/* $Id:rule.cc $ */
/*
   Copyright (C) 2007 by Jurjen Stellingwerff <jurjen@stwerff.xs4all.nl>
   Part of the Moros Project http://moros.sourceforge.net/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

#define DEBUG_ROUTINE "rule"

#include <sstream>
#include <fstream>
#include "../general/util.h"
#include "../general/log.h"
#include "../general/channel.h"
#include "rule.h"
#include "../general/general.h"

rule::rule() {
    nr=0;
    link=-1;
    name="";
    description="";
}

// Field : nr

const int rule::getNr() const { return nr; }
void rule::setNr(const int v) { nr=v; }
int rule::operator<(const class rule &ck) const { return (this->nr < ck.nr)?1:0; }

// Field : link

const string ruleLink[]={"chapter","rule","paragraph","background","race","jobs","culture","deity","skill","item","aging","gender","action"};
const int rule::getLink() const { return link; }
const string rule::showLink() const {
    if (link<0) return "";
    else return ruleLink[link];
}
void rule::setLink(const int  v) {
    if (v<0 || (unsigned int)v >= sizeof ruleLink/sizeof ruleLink[0]) link=-1;
    else link=v;
}
void rule::setLink(const string v) {
    link=-1;
    loopArray(ruleLink, tp, string) {
        if (v==*tp) {link=tp_i; break; }
    }
    if (link==-1) dbg_state("Enumerate rule.link %s has unknown '%s'", getName().c_str(), v.c_str());
}

// Field : name

const string rule::getName() const { return name; }
void rule::setName(const string v) { name=v; }

// Field : description

const string rule::getDescription() const { return description; }
void rule::setDescription(const string v) { description=v; }

void rule::save(class channel &ch) {
    ch.write("rule", "");
    ch.write("n", getNr());
    ch.write("l", getLink());
    ch.write("na", getName());
    ch.write("d", getDescription());
}

void rule::load(class channel &ch) {
    if (ch.key=="n" || ch.key=="nr") { setNr(atoi(ch.value.c_str())); ch.next(); }
    if (ch.key=="l" || ch.key=="link") { setLink(ch.value); ch.next(); }
    if (ch.key=="na" || ch.key=="name") { setName(ch.value); ch.next(); }
    if (ch.key=="d" || ch.key=="description") { setDescription(ch.value); ch.next(); }
}

void rule::xml(ofstream &f, int l, int r) {
    f << ncpy(l, "  ") << "<rule nr=\"" << getNr() <<
    "\" link=\"" << showLink() <<
    "\" name=\"" << xml_encode(getName()) <<
    "\" description=\"" << xml_encode(getDescription()) <<
    "\"/>" << endl;
}

// Repository

ruleRepository rule_repo;

ruleRepository::ruleRepository() { max_nr=0; }
class rule& ruleRepository::getRule(const string v) { return rules[v]; }
void ruleRepository::setRule(class rule& v) {
    if (v.getNr()==0) v.setNr(++max_nr);
    if (v.getName()=="") throw unnamed();
    rules[v.getName()]=v;
}
list<class rule>& ruleRepository::listRule() {
    static list<class rule> res;
    res.clear();
    loopMap(rules,v,class rule) {
        res.push_back(*v);
    }
    res.sort();
    return res;
}
void ruleRepository::delRule(const string v) { rules.erase(v); }
const bool ruleRepository::isRule(const string v) const { return rules.count(v)>0; }
void ruleRepository::save(class channel &ch) {
    loopRules(rec) {
        rec->save(ch);
    }
}

bool ruleRepository::load(class channel &ch) {
    if (ch.key=="rule") {
        ch.next();
        class rule rec;
        rec.load(ch);
        setRule(rec);
        return true;
    }
    return false;
}
